//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2013 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_AUTO_CASTS_H_
#define _BUOLA_AUTO_CASTS_H_

#include <buola/auto/exceptions.h>
#include <buola/auto/string.h>

namespace buola {

///\addtogroup utility
///@{

///\name Casts
//@{
    
///semantic cast
///
///This cast operator provides simple conversions of values from one type to
///another based on their meaning. Its main use is to convert from arithmetic
///types to string types when it's not necessary to have a lot of control
///over the conversion.
///
///Conversions are defined for the basic integer and floating-type types to and from
///the default string types, but it is possible to define other conversions
///just by specializing the template.
std::string to_string(uint8_t pInt,size_t pWidth=0,char pFill=' ');
std::string to_string(int8_t pInt,size_t pWidth=0,char pFill=' ');
std::string to_string(uint16_t pInt,size_t pWidth=0,char pFill=' ');
std::string to_string(int16_t pInt,size_t pWidth=0,char pFill=' ');
std::string to_string(uint32_t pInt,size_t pWidth=0,char pFill=' ');
std::string to_string(int32_t pInt,size_t pWidth=0,char pFill=' ');
std::string to_string(uint64_t pInt,size_t pWidth=0,char pFill=' ');
std::string to_string(int64_t pInt,size_t pWidth=0,char pFill=' ');
std::string to_string(float pReal,size_t pPrecision=0);
std::string to_string(double pReal,size_t pPrecision=0);
std::string to_string(long double pReal,size_t pPrecision=0);
std::string to_string(bool pBool);

std::wstring to_wstring(uint8_t pInt,size_t pWidth=0,char pFill=' ');
std::wstring to_wstring(int8_t pInt,size_t pWidth=0,char pFill=' ');
std::wstring to_wstring(uint16_t pInt,size_t pWidth=0,char pFill=' ');
std::wstring to_wstring(int16_t pInt,size_t pWidth=0,char pFill=' ');
std::wstring to_wstring(uint32_t pInt,size_t pWidth=0,char pFill=' ');
std::wstring to_wstring(int32_t pInt,size_t pWidth=0,char pFill=' ');
std::wstring to_wstring(uint64_t pInt,size_t pWidth=0,char pFill=' ');
std::wstring to_wstring(int64_t pInt,size_t pWidth=0,char pFill=' ');
std::wstring to_wstring(float pReal,size_t pPrecision=0);
std::wstring to_wstring(double pReal,size_t pPrecision=0);
std::wstring to_wstring(long double pReal,size_t pPrecision=0);
std::wstring to_wstring(bool pBool);

template<typename tType>
tType to_(const std::string &pStr);

template<typename tType>
tType to_(const std::wstring &pStr);

template<>
inline std::string to_<std::string>(const std::string &pStr)
{
    return pStr;
}

template<>
inline std::string to_<std::string>(const std::wstring &pStr)
{
    return utf8(pStr);
}

template<>
inline std::wstring to_<std::wstring>(const std::wstring &pStr)
{
    return pStr;
}

template<>
inline std::wstring to_<std::wstring>(const std::string &pStr)
{
    return utf32(pStr);
}

inline std::string to_string(const std::string &pStr)
{
    return pStr;
}

inline std::string to_string(const std::wstring &pStr)
{
    return utf8(pStr);
}

inline std::wstring to_wstring(const std::wstring &pStr)
{
    return pStr;
}

inline std::wstring to_wstring(const std::string &pStr)
{
    return utf32(pStr);
}


///throwing cast
///
///This cast operator behaves exactly like dynamic_cast, except that it
///throws an exception if the cast is not possible. It should be used when
///you know that the cast will always work unless there is a programming
///error, as it is easier than checking the return of dynamic_cast, and
///it wouldn't make sense to continue running the program anyway
template<typename tTo,typename tFrom>
inline tTo throwing_cast(tFrom &&pSrc)
{
    if(tTo lReturn=dynamic_cast<tTo>(std::forward<tFrom>(pSrc)))
        return lReturn;

    throw XArgument("Invalid type in throwing_cast");
}

//@}

///@}

/*namespace buola*/ }

#endif
